﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using MongoDB.Bson;
using MongoDB.Driver;
using Sustainalytics.Accounts.Service.Models;
using Sustainalytics.DataLayer.ConnectionStrings;
using Sustainalytics.MongoDB.Extensions;
using Sustainalytics.Entities;
using Sustainalytics.Entities.ConnectionStrings;
using ReferenceUniverse = Sustainalytics.Entities.ESGRatings.ReferenceUniverse;
using System.Web.Http.Cors;

namespace Sustainalytics.Accounts.Service.Controllers
{
    [EnableCors(origins: "*", headers: "*", methods: "*")]
    [RoutePrefix("api/v1/account")]
    public class AccountManagementController : ApiController
    {
        private readonly IMongoCollection<AccountPermission> _accountPermissionCollection;
        private readonly IMongoCollection<AccountProductCoverage> _accountProductCoverageCollection;
        private readonly IMongoCollection<ReferenceUniverse> _referenceUniverseCollection;

        public AccountManagementController(
            IMongoCollection<AccountPermission> accountPermissionCollection,
            IMongoCollection<AccountProductCoverage> accountProductCoverageCollection,
            IMongoCollection<ReferenceUniverse> referenceUniverseCollection)
        {
            _accountPermissionCollection = accountPermissionCollection;
            _accountProductCoverageCollection = accountProductCoverageCollection;
            _referenceUniverseCollection = referenceUniverseCollection;
        }

        [Route("{accountId}/accountPermission")]
        public HttpResponseMessage Get(Guid accountId, [FromUri]PermissionType type)
        {
            try
            {
                return Request.CreateResponse(HttpStatusCode.OK, GetAccountPermissions(accountId, type));
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
        }

        [Route("{accountId}/productPermission")]
        public HttpResponseMessage Get(Guid accountId, [FromUri]string productName)
        {
            try
            {
                return Request.CreateResponse(HttpStatusCode.OK, GetProductPermission(accountId, productName));
            }
            catch (Exception)
            {
                return Request.CreateResponse(HttpStatusCode.InternalServerError);
            }
        }

        private List<AccountPermissionDto> GetAccountPermissions(Guid accountId, PermissionType type)
        {
            var builder = Builders<AccountPermission>.Filter;
            var filter = builder.Eq(a => a.AccountId, accountId) &
                         builder.Eq(a => a.Type, type);

            var accountPermissions = _accountPermissionCollection.Find(filter)
                .ToEnumerable()
                .Select(x => new AccountPermissionDto
                {
                    AccountId = x.AccountId,
                    Name = x.Name,
                    IsActive = x.IsActive,
                    CoveredIndices = new List<string>(),
                    UncoveredIndices = new List<string>()
                })
                .ToList();

            var accountProductCoverages = GetAccountProductCoverages(accountId);

            accountPermissions.ForEach(x =>
            {
                var key = new KeyValuePair<Guid, string>(x.AccountId, x.Name);
                var coverage = accountProductCoverages.ContainsKey(key)
                    ? accountProductCoverages[key]
                    : null;

                if (coverage == null) return;

                x.CoveredIndices = coverage.CoveredIndices;
                x.UncoveredIndices = coverage.UncoveredIndices;
            });

            return accountPermissions;
        }

        private Dictionary<KeyValuePair<Guid, string>, AccountPermissionDto> GetAccountProductCoverages(Guid accountId)
        {
            var accountProductCoverage = _accountProductCoverageCollection
                .Find(x => x.AccountId == accountId)
                .ToList();

            var referenceUniverses = _referenceUniverseCollection
                .Find(x => x.Name != "Default")
                .Project(x => x.Name)
                .ToList();

            var result = accountProductCoverage.Select(x => new AccountPermissionDto()
            {
                AccountId = x.AccountId,
                Name = x.ResearchProduct,
                CoveredIndices = x.ReferenceUniverses,
                UncoveredIndices = referenceUniverses.Where(ru => !x.ReferenceUniverses.Contains(ru)).ToList()
            })
            .ToDictionary(k => new KeyValuePair<Guid, string>(k.AccountId, k.Name));

            return result;
        }

        private object GetProductPermission(Guid accountId, string name)
        {
            var builder = Builders<AccountPermission>.Filter;
            var filter = builder.Eq(a => a.AccountId, accountId) &
                         builder.Eq(a => a.Type, PermissionType.ResearchProduct) &
                         builder.Eq(a => a.Name, name);

            var accountPermission = _accountPermissionCollection.Find(filter)
                .ToEnumerable()
                .Select(x => new
                {
                    Covered = x.Claims.Where(c => c.IsActive).Select(c => c.Name).ToList(),
                    Uncovered = x.Claims.Where(c => !c.IsActive).Select(c => c.Name).ToList()
                })
                .SingleOrDefault();

            return accountPermission;
        }


    }
}
